#pragma once

#include <iostream>
#include <cerrno>
#include "Connection.hpp"
#include "protocol.hpp"
#include "Calculate.hpp"
#include "Log.hpp"


using namespace protocol;
using namespace CalculateNS;

const static int buffer_size = 1024;

//实际上HandlerConnection,和Acceptor 都是Connect的衍生。
//Handler.. 是为了完成用户的需求而设计  ， Acceptor 是为了能够接受客户的请求。
//和之前的sockfd类似，对于sockfd，会有两种情况，一个是LIstensock的读就绪，代表有新client连接了
// 对与普通的sockfd ，代表要处理client的需求。

class HandlerConnection
{
public:
    static void HandlerRequest(Connection* conn)
    {
        std::string& inbuffer = conn->InBuffer();
        std::string message;
        Factory factory;
        CalculateNS::Calculate calculate;//业务处理：网络计算机
        auto req = factory.BuildRequest();//先建造一个需求，需求内容等，解包后，才进行构建
        // 1. 明确报文边界，解决粘报问题
        while(Decode(inbuffer,&message))//inbuffer可能有多个package, 一次性处理完，message 每次只储存一个包的内容
        {
            // message 一定是一个完整的报文，符合协议的！
            // 2. 反序列化
            if (!req->Deserialize(message))
                continue;
            // 3. 业务处理
            auto resp = calculate.Cal(req);
            // 4. 对相应进行序列化
            std::string responsestr;
            resp->Serialize(&responsestr);
            // 5. 封装完整报文
            responsestr = Encode(responsestr);
            // 6. 将应答全部追加到outbuffer中
            conn->AddOutBuffer(responsestr);
        }
         // 考虑发送的问题了
        if (!conn->OutBufferEmpty())
        {
            //conn->_sender(conn); // 对写事件，直接发！！！--- 不代表能全部发完！
        }
    }
    // 在这里读取的时候，我们关系数据是什么格式？协议是什么样子的吗？
    // 不关心！！！我们只负责把本轮属于完全读取完毕 --- 把读到的字节流数据，交给上层 --- 由上层进行分析处理
    static void Recver(Connection *conn)
    {
        errno = 0;
        char buffer[1024];
        while(true)
        {
            int n = ::recv(conn->SockFd(), buffer, sizeof(buffer)-1, 0);
            if(n > 0)
            {
                buffer[n] = 0;
                conn->AddInBuffer(buffer);
            }
            else{
                // std::cout << "................... errno:" << errno << std::endl;
                if(errno == EAGAIN){
                    break;
                }else if(errno == EINTR){
                    continue;
                }else{
                    //真正的错误
                    conn->_excepter(conn);
                    return;
                }
            }
        }
        std::cout << "sockfd# " << conn->SockFd() << ":\n"
                  << conn->InBuffer() << std::endl;
        // 尝试分析处理报文 -- 半个，一个半， 10个，11个半
        HandlerRequest(conn);
    }
    static void Sender(Connection *conn)
    {
        std::string& outbuffer = conn->OutBuffer();
        while(true)
        {
            ssize_t n = send(conn->SockFd(), outbuffer.c_str(), outbuffer.size(), 0);
            if(n >= 0){
                outbuffer.erase(0, n);//已经交给OS，直接移除了  
                if(outbuffer.empty()){
                    break;
                }
            }else{
                if(errno == EAGAIN)
                    break;
                else if(errno == EINTR)
                    continue;
                else{
                    //conn->_excepter(conn);
                    return;
                }
            }
        }
        // 走到这里，意味着什么？我们本轮发满了，但是数据可能没发完，为什么没发完呢？
        // 开启对conn->SockFd() EPOLLOUT的关心！！！！！， 如何开启对于特定一个connection对应的写事件关心呢？？？
        if (!conn->OutBufferEmpty())
        {
            //conn->_R->EnableReadWrite(conn->SockFd(), true, true);
        }
        else
        {
            //conn->_R->EnableReadWrite(conn->SockFd(), true, false);
        }
    }
    static void Excepter(Connection *conn)
    {
        lg.LogMessage(Info, "connection erase done, who: %d\n", conn->SockFd());
        errno = 0;
        // 从epoll中移除对conn->Sockfd的关心
        // unordered_map 移除conn

        //conn->_R->RemoveConnection(conn->SockFd());

        // 关闭conn->Sockfd
        conn->Close();
        // delete conn
        delete conn;
    }
};
